﻿using Taype.Trading.BTC.MtGoxAPIClient;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using BitCoinSharp;
using Taype.Trading.BTC.MtGoxAPIClient.JSONObjects;
using System.Collections.Generic;
using Org.BouncyCastle.Utilities.Encoders;

namespace MtGoxAPIClient_test
{
    
    
    /// <summary>
    ///This is b test class for v0Test and is intended
    ///to contain all v0Test Unit Tests
    ///</summary>
    [TestClass()]
    public class v0Test
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in b class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for v0 Constructor
        ///</summary>
        [TestMethod()]
        public void v0ConstructorTest()
        {
            v0 target = new v0();
            Assert.IsNotNull(target);
        }

        /// <summary>
        ///A test for btcAddress
        ///</summary>
        [TestMethod()]
        public void btcAddressTest()
        {
            v0 target = new v0();
            string description = String.Format("Test address {0}", DateTime.Now.ToLongDateString());
            Address actual = null;
            actual = target.btcAddress(description);
            // make sure the string representation of the returned address is: a) correct length b) contains only valid Base-58 characters
            Assert.AreEqual(actual.ToString().Length, 34);
        }

        /// <summary>
        ///A test for buyBTC
        ///</summary>
        [TestMethod()]
        public void buyBTCTest()
        {
            v0 target = new v0();
            double amount = 0.01;
            MtGoxCurrencySymbol currency = MtGoxCurrencySymbol.USD;
            // initialize price to random double < 0.02
            double price = 0.01 + (new Random()).NextDouble() * 0.01;
            List<MtGoxOrder> actual;
            actual = target.buyBTC(amount, currency, price);
            // now we should find a trade in our open trade list that has that amount via getOrder
            MtGoxOrder toFind = actual.Find(
                delegate(MtGoxOrder ord)
                {
                    return ord.price == Math.Round(price, 5);
                }
            );
            Assert.IsNotNull(toFind);
        }

        /// <summary>
        ///A test for cancelOrder
        ///</summary>
        [TestMethod()]
        public void cancelOrderTest()
        {
            v0 target = new v0();
            // let's first create a dummy order
            double amount = 0.01;
            MtGoxCurrencySymbol currency = MtGoxCurrencySymbol.USD;
            // initialize price to random double < 0.02
            double price = 0.01 + (new Random()).NextDouble() * 0.01;
            List<MtGoxOrder> actual;
            actual = target.buyBTC(amount, currency, price);
            // now let's find our dummy order ...
            // now we should find a trade in our open trade list that has that amount via getOrder
            MtGoxOrder toFind = actual.Find(
                delegate(MtGoxOrder ord)
                {
                    return ord.price == Math.Round(price, 5);
                }
            );
            string testOid = toFind.oid;
            MtGoxOrderType type = MtGoxOrderType.Buy;
            actual = target.cancelOrder(testOid, type);
            // now if our cancel request was successful we should not find our order in our list of current orders
            actual = target.getOrders(MtGoxOrderType.Buy, MtGoxOrderStatus.Active, 0);
            toFind = null;
            // if there are still open orders make sure our dummy one is no longer in there
            if (actual != null)
            {
                toFind = actual.Find(
               delegate(MtGoxOrder ord)
               {
                   return ord.oid == testOid;
               }
                );
            }
            Assert.IsNull(toFind);
        }

        /// <summary>
        ///A test for getDepth
        ///</summary>
        [TestMethod()]
        public void getDepthTest()
        {
            v0 target = new v0();
            MtGoxCurrencySymbol currency = MtGoxCurrencySymbol.USD;
            MtGoxDepthInfo actual;
            actual = target.getDepth(currency);
            Assert.AreNotEqual(actual.asks.Count, 0);
            Assert.AreNotEqual(actual.bids.Count, 0);
        }

        /// <summary>
        ///A test for getFunds
        ///</summary>
        [ExpectedException(typeof(NotImplementedException))]
        [TestMethod()]
        public void getFundsTest()
        {
            v0 target = new v0();
            target.getFunds();
        }

        /// <summary>
        ///A test for getOrders
        ///</summary>
        [TestMethod()]
        public void getOrdersTest()
        {
            v0 target = new v0();
            MtGoxOrder expected = new MtGoxOrder();
            expected.amount = 0.01;
            expected.currency = MtGoxCurrencySymbol.USD;
            expected.item = MtGoxCurrencySymbol.BTC;
            // create a random price above $100
            double randomPrice = 100.0 + (new Random()).NextDouble() * 100;
            expected.price = Math.Round(randomPrice, 5);
            List<MtGoxOrder> actual;
            target.sellBTC(0.01, MtGoxCurrencySymbol.USD, randomPrice);
            MtGoxOrderType type = MtGoxOrderType.Buy;
            MtGoxOrderStatus status = MtGoxOrderStatus.Invalid;
            int oid = 0;
            actual = target.getOrders(type, status, oid);
            // now see if we can find our order in the list
            MtGoxOrder toFind = actual.Find(
                delegate(MtGoxOrder ord)
                {
                    return ord.price == Math.Round(randomPrice, 5);
                }
            );
            Assert.AreEqual(expected.amount, toFind.amount);
            Assert.AreEqual(expected.currency, toFind.currency);
            Assert.AreEqual(expected.item, toFind.item);
            Assert.AreEqual(expected.price, toFind.price);
        }

        /// <summary>
        ///A test for getTrades
        ///</summary>
        [TestMethod()]
        public void getTradesTest()
        {
            v0 target = new v0(); 
            string sinceTradeID = "0"; 
            List<MtGoxTrade> actual;
            actual = target.getTrades(sinceTradeID);
            Assert.IsNotNull(actual);
        }

        /// <summary>
        ///A test for history_CUR
        ///</summary>
        [TestMethod()]
        public void history_CURTest()
        {
            v0 target = new v0();
            MtGoxCurrencySymbol currency = MtGoxCurrencySymbol.USD;
            string expected = null;
            string actual;
            actual = target.history_CUR(currency);
            // returned CSV string should look something like this:
            // "Index,Date,Type,Info,Value,Balance\n1,\"2012-01-09 04:07:20\",earned,\"BTC sold: [tid:1326082040762258] 0.01000000 BTC at $7.10000\",0.071,0.071\n2,\"2012-01-09 04:07:20\",fee,\"BTC sold: [tid:1326082040762258] 0.01000000 BTC at $7.10000 (0.6% fee)\",0.00043,0.07057\n"
            // check for header row
            string[] rows = actual.Split(new char[] { '\n' });
            for (int i = 0; i < rows.Length; i++)
            {
                if (i == 0)
                {
                    Assert.AreEqual(rows[i], "Index,Date,Type,Info,Value,Balance");
                }
                if (rows[i] != "")
                {
                    string[] tokens = rows[i].Split(new char[] { ',' });
                    Assert.AreEqual(tokens.Length, 6);
                }
            }
        }

        /// <summary>
        ///A test for info
        ///</summary>
        [TestMethod()]
        public void infoTest()
        {
            // TODO: A much more thorough implementation of this test
            // jsonDataStr will look as follows: "{\"Login\":\"taype-autotrader\",\"Index\":\"110333\",\"Rights\":[\"deposit\",\"get_info\",\"trade\",\"withdraw\"],\"Language\":\"en_US\",\"Created\":\"2012-01-02 20:51:43\",\"Last_Login\":\"2012-01-06 20:00:15\",\"Wallets\":{\"BTC\":{\"Balance\":{\"value\":\"0.86053625\",\"value_int\":\"86053625\",\"display\":\"0.86053625\\u00a0BTC\",\"currency\":\"BTC\"},\"Operations\":1,\"Daily_Withdraw_Limit\":{\"value\":\"400.00000000\",\"value_int\":\"40000000000\",\"display\":\"400.00000000\\u00a0BTC\",\"currency\":\"BTC\"},\"Monthly_Withdraw_Limit\":null,\"Max_Withdraw\":{\"value\":\"400.00000000\",\"value_int\":\"40000000000\",\"display\":\"400.00000000\\u00a0BTC\",\"currency\":\"BTC\"}},\"USD\":{\"Balance\":{\"value\":\"0.00000\",\"value_int\":\"0\",\"display\":\"$0.00000\",\"currency\":\"USD\"},\"Operations\":0,\"Daily_Withdraw_Limit\":{\"value\":\"1000.00000\",\"value_int\":\"100000000\",\"display\":\"$1,000.00000\",\"currency\":\"USD\"},\"Monthly_Withdraw_Limit\":{\"value\":\"10000.00000\",\"value_int\":\"1000000000\",\"display\":\"$10,000.00000\",\"currency\":\"USD\"},\"Max_Withdraw\":{\"value\":\"1000.00000\",\"value_int\":\"100000000\",\"display\":\"$1,000.00000\",\"currency\":\"USD\"}}},\"Trade_Fee\":0.6}"
            v0 target = new v0();
            MtGoxHistoryItem actual;
            actual = target.info();
            Assert.IsNotNull(actual);
        }

        /// <summary>
        ///A test for redeemCode
        ///</summary>
        [TestMethod()]
        public void redeemCodeTest()
        {
            // TODO: Need to obtain a sample coupon code to test this method
            v0 target = new v0();
            string code = string.Empty;
            MtGoxCouponRedemptionResult expected = null;
            MtGoxCouponRedemptionResult actual;
            actual = target.redeemCode(code);
            //Assert.AreEqual(expected, actual);
            Assert.Inconclusive("Need to obtain some test coupons to implement this test");
        }

        /// <summary>
        ///A test for sellBTC
        ///</summary>
        [TestMethod()]
        public void sellBTCTest()
        {
            v0 target = new v0(); // TODO: Initialize to an appropriate value
            double amount = 0.01; // TODO: Initialize to an appropriate value
            MtGoxCurrencySymbol currency = MtGoxCurrencySymbol.USD; // TODO: Initialize to an appropriate value
            double price = 100.0; // TODO: Initialize to an appropriate value
            List<MtGoxOrder> actual;
            actual = target.sellBTC(amount, currency, price);
            Assert.IsNotNull(actual);
        }

        /// <summary>
        ///A test for ticker
        ///</summary>
        [TestMethod()]
        public void tickerTest()
        {
            v0 target = new v0();
            MtGoxTickerItem actual = null;
            actual = target.ticker();
            Assert.IsNotNull(actual);
        }

        /// <summary>
        ///A test for withdraw
        ///</summary>
        [TestMethod()]
        public void withdrawTest()
        {
            v0 target = new v0();
            MtGoxWithdrawalType group1 = MtGoxWithdrawalType.BTC2CODE;
            Address btca = new Address(new NetworkParameters(), "1ENcrmysWoTzeBm8E9jk4rJz5HKYLyQDBS");
            double amount = 0.0001;
            MtGoxCurrencySymbol currency = MtGoxCurrencySymbol.CAD;
            string green = "";
            object[] expected = null;
            object[] actual;
            actual = target.withdraw(group1, btca, amount, currency, green);
            Assert.AreEqual(expected, actual);
        }

        ///// <summary>
        /////A test for getOrders
        /////</summary>
        //[TestMethod()]
        //public void getOrdersTest1()
        //{
        //    v0 target = new v0(); // TODO: Initialize to an appropriate value
        //    List<MtGoxOrder> expected = null; // TODO: Initialize to an appropriate value
        //    List<MtGoxOrder> actual;
        //    actual = target.getOrders();
        //    Assert.AreEqual(expected, actual);
        //    Assert.Inconclusive("Verify the correctness of this test method.");
        //}
    }
}
